home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / system-config-printer / AdvancedServerSettings.py next >
Encoding:
Python Source  |  2010-09-28  |  12.6 KB  |  364 lines

  1. #!/usr/bin/env python
  2.  
  3. ## system-config-printer
  4.  
  5. ## Copyright (C) 2008, 2009, 2010 Red Hat, Inc.
  6. ## Authors:
  7. ##  Tim Waugh <twaugh@redhat.com>
  8.  
  9. ## This program is free software; you can redistribute it and/or modify
  10. ## it under the terms of the GNU General Public License as published by
  11. ## the Free Software Foundation; either version 2 of the License, or
  12. ## (at your option) any later version.
  13.  
  14. ## This program is distributed in the hope that it will be useful,
  15. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. ## GNU General Public License for more details.
  18.  
  19. ## You should have received a copy of the GNU General Public License
  20. ## along with this program; if not, write to the Free Software
  21. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  
  23. from gettext import gettext as _
  24. import cups
  25. import gobject
  26. import gtk
  27. import os
  28. import socket
  29. import tempfile
  30. import time
  31.  
  32. from errordialogs import *
  33.  
  34. class AdvancedServerSettings:
  35.     RESOURCE="/admin/conf/cupsd.conf"
  36.  
  37.     def __init__ (self, gui, on_apply=None):
  38.         self.cupsconn = gui.cups
  39.         self.on_apply = on_apply
  40.  
  41.         # Signal handler IDs.
  42.         self.handler_ids = {}
  43.  
  44.         self.dialog = gui.ServerSettingsDialog
  45.         browse_frame = gui.frameBrowseServers
  46.         self.browse_treeview = gui.tvBrowseServers
  47.         self.rbPreserveJobFiles = gui.rbPreserveJobFiles
  48.         self.rbPreserveJobHistory = gui.rbPreserveJobHistory
  49.         self.rbPreserveJobNone = gui.rbPreserveJobNone
  50.         self.add = gui.btAdvServerAdd
  51.         self.remove = gui.btAdvServerRemove
  52.  
  53.         selection = self.browse_treeview.get_selection ()
  54.         selection.set_mode (gtk.SELECTION_MULTIPLE)
  55.         self.connect (selection, 'changed', self.on_treeview_selection_changed)
  56.  
  57.         for column in self.browse_treeview.get_columns():
  58.             self.browse_treeview.remove_column(column)
  59.         col = gtk.TreeViewColumn ('', gtk.CellRendererText (), text=0)
  60.         self.browse_treeview.append_column (col)
  61.  
  62.         # Fetch cupsd.conf
  63.         f = tempfile.TemporaryFile ()
  64.         try:
  65.             self.cupsconn.getFile (self.RESOURCE, file=f)
  66.         except cups.HTTPError, (s,):
  67.             show_HTTP_Error (s, self.dialog)
  68.             raise
  69.  
  70.         def parse_yesno (line):
  71.             arg1 = line.split (' ')[1].strip ()
  72.             if arg1 in ['true', 'on', 'enabled', 'yes']:
  73.                 return True
  74.             if arg1 in ['false', 'off', 'disabled', 'no', '0']:
  75.                 return False
  76.             try:
  77.                 if int (arg1) != 0:
  78.                     return True
  79.             except:
  80.                 pass
  81.             raise RuntimeError
  82.  
  83.         preserve_job_history = True
  84.         preserve_job_files = False
  85.         browsing = True
  86.         self.browse_poll = []
  87.         f.seek (0)
  88.         for line in f.readlines ():
  89.             l = line.lower ().strip ()
  90.             if l.startswith ("preservejobhistory "):
  91.                 try:
  92.                     preserve_job_history = parse_yesno (l)
  93.                 except:
  94.                     pass
  95.             elif l.startswith ("preservejobfiles "):
  96.                 try:
  97.                     preserve_job_files = parse_yesno (l)
  98.                 except:
  99.                     pass
  100.             elif l.startswith ("browsing "):
  101.                 try:
  102.                     browsing = parse_yesno (l)
  103.                 except:
  104.                     pass
  105.             elif l.startswith ("browsepoll "):
  106.                 self.browse_poll.append (line[len ("browsepoll "):].strip ())
  107.  
  108.         browse_frame.set_sensitive (browsing)
  109.  
  110.         if preserve_job_files:
  111.             self.rbPreserveJobFiles.set_active (True)
  112.         elif preserve_job_history:
  113.             self.rbPreserveJobHistory.set_active (True)
  114.         else:
  115.             self.rbPreserveJobNone.set_active (True)
  116.  
  117.         self.preserve_job_history = preserve_job_history
  118.         self.preserve_job_files = preserve_job_files
  119.  
  120.         model = gtk.ListStore (gobject.TYPE_STRING)
  121.         self.browse_treeview.set_model (model)
  122.         for server in self.browse_poll:
  123.             model.append (row=[server])
  124.  
  125.     def connect (self, widget, signal, handler, reason=None):
  126.         id = widget.connect (signal, handler)
  127.         if not self.handler_ids.has_key (reason):
  128.             self.handler_ids[reason] = []
  129.         self.handler_ids[reason].append ((widget, id))
  130.  
  131.     def disconnect (self, reason=None):
  132.         if self.handler_ids.has_key (reason):
  133.             for (widget, id) in self.handler_ids[reason]:
  134.                 widget.disconnect (id)
  135.             del self.handler_ids[reason]
  136.  
  137.     def on_treeview_selection_changed (self, selection):
  138.         self.remove.set_sensitive (selection.count_selected_rows () != 0)
  139.  
  140.     def on_add_clicked (self, button):
  141.         model = self.browse_treeview.get_model ()
  142.         iter = model.insert (0, row=[_("Enter IP address")])
  143.         button.set_sensitive (False)
  144.         col = self.browse_treeview.get_columns ()[0]
  145.         cell = col.get_cell_renderers ()[0]
  146.         cell.set_property ('editable', True)
  147.         self.browse_treeview.set_cursor ((0,), col, start_editing=True)
  148.         self.connect (cell, 'edited', self.on_browse_poll_edited,
  149.                       'edit')
  150.         self.connect (cell, 'editing-canceled', self.on_browse_poll_edit_cancel,
  151.                       'edit')
  152.  
  153.     def on_browse_poll_edited (self, cell, path, newvalue):
  154.         model = self.browse_treeview.get_model ()
  155.         iter = model.get_iter (path)
  156.         model.set_value (iter, 0, newvalue)
  157.         cell.stop_editing (canceled=False)
  158.         cell.set_property ('editable', False)
  159.         self.add.set_sensitive (True)
  160.         self.disconnect ('edit')
  161.  
  162.         valid = True
  163.         # Check that it's a valid IP address or hostname.
  164.         # First, is it an IP address?
  165.         try:
  166.             socket.getaddrinfo (newvalue, '0', socket.AF_UNSPEC, 0, 0,
  167.                                 socket.AI_NUMERICHOST)
  168.         except socket.gaierror:
  169.             # No.  Perhaps it's a hostname.
  170.             labels = newvalue.split (".")
  171.             seen_alpha = False
  172.             for label in labels:
  173.                 if (label[0] == '-' or
  174.                     label.endswith ('-')):
  175.                     valid = False
  176.                     break
  177.                 for char in label:
  178.                     if not seen_alpha:
  179.                         if char.isalpha ():
  180.                             seen_alpha = True
  181.  
  182.                     if not (char.isalpha () or
  183.                             char.isdigit () or
  184.                             char == '-'):
  185.                         valid = False
  186.                         break
  187.  
  188.                 if not valid:
  189.                     break
  190.  
  191.             if valid and not seen_alpha:
  192.                 valid = False
  193.  
  194.         if valid:
  195.             count = 0
  196.             i = model.get_iter_first ()
  197.             while i:
  198.                 if model.get_value (i, 0) == newvalue:
  199.                     count += 1
  200.                     if count == 2:
  201.                         valid = False
  202.                         selection = self.browse_treeview.get_selection ()
  203.                         selection.select_iter (i)
  204.                         break
  205.                 i = model.iter_next (i)
  206.         else:
  207.             model.remove (iter)
  208.  
  209.     def on_browse_poll_edit_cancel (self, cell):
  210.         cell.stop_editing (canceled=True)
  211.         cell.set_property ('editable', False)
  212.         model = self.browse_treeview.get_model ()
  213.         iter = model.get_iter ((0,))
  214.         model.remove (iter)
  215.         self.add.set_sensitive (True)
  216.         self.remove.set_sensitive (False)
  217.         self.disconnect ('edit')
  218.  
  219.     def on_remove_clicked (self, button):
  220.         model = self.browse_treeview.get_model ()
  221.         selection = self.browse_treeview.get_selection ()
  222.         rows = selection.get_selected_rows ()
  223.         refs = map (lambda path: gtk.TreeRowReference (model, path),
  224.                     rows[1])
  225.         for ref in refs:
  226.             path = ref.get_path ()
  227.             iter = model.get_iter (path)
  228.             model.remove (iter)
  229.  
  230.     def on_response (self, dialog, response):
  231.         if (response == gtk.RESPONSE_CANCEL or
  232.             response != gtk.RESPONSE_OK):
  233.             self.disconnect ()
  234.             del self
  235.             return
  236.  
  237.         # See if there are changes.
  238.         preserve_job_files = self.rbPreserveJobFiles.get_active ()
  239.         preserve_job_history = (preserve_job_files or
  240.                                 self.rbPreserveJobHistory.get_active ())
  241.         model = self.browse_treeview.get_model ()
  242.         browse_poll = []
  243.         iter = model.get_iter_first ()
  244.         while iter:
  245.             browse_poll.append (model.get_value (iter, 0))
  246.             iter = model.iter_next (iter)
  247.  
  248.         if (set (browse_poll) == set (self.browse_poll) and
  249.             preserve_job_files == self.preserve_job_files and
  250.             preserve_job_history == self.preserve_job_history):
  251.             self.disconnect ()
  252.             del self
  253.             return
  254.  
  255.         # Fetch cupsd.conf afresh
  256.         f = tempfile.TemporaryFile ()
  257.         try:
  258.             self.cupsconn.getFile (self.RESOURCE, file=f)
  259.         except cups.HTTPError, (s,):
  260.             show_HTTP_Error (s, dialog)
  261.             return
  262.  
  263.         job_history_line = job_files_line = browsepoll_lines = ""
  264.  
  265.         # Default is to preserve job history
  266.         if not preserve_job_history:
  267.             job_history_line = "PreserveJobHistory No\n"
  268.  
  269.         # Default is not to preserve job files.
  270.         if preserve_job_files:
  271.             job_files_line = "PreserveJobFiles Yes\n"
  272.  
  273.         for server in browse_poll:
  274.             browsepoll_lines += "BrowsePoll %s\n" % server
  275.  
  276.         f.seek (0)
  277.         conf = tempfile.TemporaryFile ()
  278.         wrote_preserve_history = wrote_preserve_files = False
  279.         wrote_browsepoll = False
  280.         has_browsepoll = False
  281.         lines = f.readlines ()
  282.         for line in lines:
  283.             l = line.lower ().strip ()
  284.             if l.startswith ("browsepoll "):
  285.                 has_browsepoll = True
  286.                 break
  287.  
  288.         for line in lines:
  289.             l = line.lower ().strip ()
  290.             if l.startswith ("preservejobhistory "):
  291.                 if wrote_preserve_history:
  292.                     # Don't write out another line with this keyword.
  293.                     continue
  294.                 # Alter this line before writing it out.
  295.                 line = job_history_line
  296.                 wrote_preserve_history = True
  297.             elif l.startswith ("preservejobfiles "):
  298.                 if wrote_preserve_files:
  299.                     # Don't write out another line with this keyword.
  300.                     continue
  301.                 # Alter this line before writing it out.
  302.                 line = job_files_line
  303.                 wrote_preserve_files = True
  304.             elif (has_browsepoll and
  305.                   l.startswith ("browsepoll ")):
  306.                 if wrote_browsepoll:
  307.                     # Ignore extra BrowsePoll lines.
  308.                     continue
  309.                 # Write new BrowsePoll section.
  310.                 conf.write (browsepoll_lines)
  311.                 wrote_browsepoll = True
  312.                 # Don't write out the original BrowsePoll line.
  313.                 continue
  314.             elif (not has_browsepoll and
  315.                   l.startswith ("browsing ")):
  316.                 if not wrote_browsepoll:
  317.                     # Write original Browsing line.
  318.                     conf.write (line)
  319.                     # Write new BrowsePoll section.
  320.                     conf.write (browsepoll_lines)
  321.                     wrote_browsepoll = True
  322.                     continue
  323.  
  324.             conf.write (line)
  325.  
  326.         if not wrote_preserve_history:
  327.             conf.write (job_history_line)
  328.         if not wrote_preserve_files:
  329.             conf.write (job_files_line)
  330.         if not wrote_browsepoll:
  331.             conf.write (browsepoll_lines)
  332.  
  333.         conf.flush ()
  334.         fd = conf.fileno ()
  335.         os.lseek (fd, 0, os.SEEK_SET)
  336.         try:
  337.             self.cupsconn.putFile ("/admin/conf/cupsd.conf", fd=fd)
  338.         except cups.HTTPError, (s,):
  339.             show_HTTP_Error (s, dialog)
  340.             return
  341.  
  342.         # Give the server a chance to process our request.
  343.         time.sleep (1)
  344.  
  345.         # Now reconnect, in case the server needed to reload.
  346.         try:
  347.             attempt = 1
  348.             while attempt <= 5:
  349.                 try:
  350.                     self.cupsconn._connect ()
  351.                     break
  352.                 except RuntimeError:
  353.                     # Connection failed.
  354.                     time.sleep (1)
  355.                     attempt += 1
  356.         except AttributeError:
  357.             # _connect method is part of the authconn.Connection
  358.             # interface, so don't fail if that method doesn't exist.
  359.             pass
  360.  
  361.         self.disconnect ()
  362.         self.on_apply ()
  363.         del self
  364.